#pragma once
#include "../source/message.hpp"
#include "../source/net.hpp"
#include "../source/dispacher.hpp"
#include "Rpc_router.hpp"
#include "Rpc_registry.hpp"
#include "../client/Rpc_client.hpp"
#include "Rpc_topic.hpp"

namespace ns_rpc_server
{
    class RegistryServer
    {
    public: 
        using ptr = std::shared_ptr<RegistryServer>;
        //注册中心服务器
        RegistryServer(int port)
        :_pdmanager(std::make_shared<ns_server_registry::PDManager>())
        ,_dispacher(std::make_shared<ns_dispacher::Dispacher>())
        {
            //服务注册/发现的回调
            auto pd_msg = std::bind(&ns_server_registry::PDManager::OnServiceRequest,_pdmanager.get(),std::placeholders::_1,std::placeholders::_2);
            _dispacher->Registercb<ServiceRequest>(Mtype::SERVICE_REQ,pd_msg);

            auto service_msg = std::bind(&ns_dispacher::Dispacher::OnMessage,_dispacher.get(),std::placeholders::_1,std::placeholders::_2);
            _rpc_server = ns_net::ServerFactory::ServerCreate(port);
            _rpc_server->SetMessageCallback(service_msg);
            auto close_cb = std::bind(&RegistryServer::OnShutDown,this,std::placeholders::_1);
            _rpc_server->SetCloseCallback(close_cb);
            
        }
        void Start()
        {
            _rpc_server->start();
        }
    private:
        void OnShutDown(const BaseConnection::ptr &conn)
        {
            _pdmanager->OnShutDown(conn);
        }
        ns_server_registry::PDManager::ptr _pdmanager;
        ns_dispacher::Dispacher::ptr _dispacher;
        BaseServer::ptr _rpc_server;
    };

    class RpcServer
    {
    public:
        using ptr = std::shared_ptr<RpcServer>;
        //access_addr：rpc服务提供端的地址信息，它必须是 对外访问 的地址 ,也就是公网地址（云服务器，监听-内/私网地址，访问-公网地址）
        //registery_addr：注册中心服务端的地址信息，服务启动后，用于去服务中心进行服务注册
        RpcServer(const Address& access_addr,bool enableRegistry = false,const Address& registery_addr = Address())
        :_enableRegistry(enableRegistry)
        ,_access_addr(access_addr)
        ,_dispacher(std::make_shared<ns_dispacher::Dispacher>())
        ,_router(std::make_shared<ns_router::RpcRouter>())
        {
            if(_enableRegistry)
            {//若为真，实例化注册客户端，通过它向注册中心进行服务注册
                _reg_client = std::make_shared<ns_rpc_client::RegisteryClient>(registery_addr.first,registery_addr.second);
            }
            auto rpc_cb = std::bind(&ns_router::RpcRouter::OnRpcRequest,_router.get(),std::placeholders::_1,std::placeholders::_2);
            _dispacher->Registercb<RpcRequest>(Mtype::RPC_REQ,rpc_cb);

            auto rsp_cb = std::bind(&ns_dispacher::Dispacher::OnMessage,_dispacher.get(),std::placeholders::_1,std::placeholders::_2);

            _rpc_server = ns_net::ServerFactory::ServerCreate(access_addr.second);
            _rpc_server->SetMessageCallback(rsp_cb);
        }
        void RegisterMethod(const ns_router::ServiceDescribe::ptr& sd)
        {
            //如果有注册中心的地址信息，得告诉注册中心，我可以提供一个服务
            if(_enableRegistry)
            {
                _reg_client->RegisterService(sd->GetMethodname(),_access_addr);
            }
            _router->RegisterMethod(sd);

        }
        void Start()
        {
            _rpc_server->start();
        }
    private:
        Address _access_addr;
        bool _enableRegistry;
        ns_rpc_client::RegisteryClient::ptr _reg_client;
        ns_router::RpcRouter::ptr _router;
        ns_dispacher::Dispacher::ptr _dispacher;
        BaseServer::ptr _rpc_server;
    };


    class TopicServer
    {
    public: 
        using ptr = std::shared_ptr<TopicServer>;
        //注册中心服务器
        TopicServer(int port)
        :_topic_manager(std::make_shared<ns_server_topic::TopicManager>())
        ,_dispacher(std::make_shared<ns_dispacher::Dispacher>())
        {
            //服务注册/发现的回调
            auto tm_msg = std::bind(&ns_server_topic::TopicManager::OnTopicRequest,_topic_manager.get(),std::placeholders::_1,std::placeholders::_2);
            _dispacher->Registercb<TopicRequest>(Mtype::TOPIC_REQ,tm_msg);

            auto service_msg = std::bind(&ns_dispacher::Dispacher::OnMessage,_dispacher.get(),std::placeholders::_1,std::placeholders::_2);
            _rpc_server = ns_net::ServerFactory::ServerCreate(port);
            _rpc_server->SetMessageCallback(service_msg);
            auto close_cb = std::bind(&TopicServer::OnShutDown,this,std::placeholders::_1);
            _rpc_server->SetCloseCallback(close_cb);
            
        }
        void Start()
        {
            _rpc_server->start();
        }
    private:
        void OnShutDown(const BaseConnection::ptr &conn)
        {
            _topic_manager->OnShutDown(conn);
        }
        ns_server_topic::TopicManager::ptr _topic_manager;
        ns_dispacher::Dispacher::ptr _dispacher;
        BaseServer::ptr _rpc_server;
    };
}